/*
 * Copyright (C) 2014 Lucid Wolf
 * Copyright 2002 by Darius Bacon <darius@wry.me>.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Darius Bacons original Copywrite
 * Copyright 2002 by Darius Bacon <darius@wry.me>.
 * 
 * Permission is granted to anyone to use this software for any
 * purpose on any computer system, and to redistribute it freely,
 * subject to the following restrictions:
 * 
 * 1. The author is not responsible for the consequences of use of
 *    this software, no matter how awful, even if they arise from 
 *    defects in it.
 * 
 * 2. The origin of this software must not be misrepresented, either
 *    by explicit claim or by omission.
 * 
 * 3. Altered versions must be plainly marked as such, and must not
 *    be misrepresented as being the original software.
 */

package com.lucidhex.equation;

import com.lucidhex.equation.parser.Expr;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * Started with Darius Bacons original code heavy modification to remove 
 * static dependencies and overall cleanup
 * 1.) Variables are tracked at the equation level and require a default value
 * 2.) Added a toUpperCase operator of all word tokens during parsing so that 
 * equation is not case sensative for variable or Sub names
 * 3.) Added substitutions to Equation so users can break down equations 
 * and debug them requires a $ to the name
 * @author Lucid Wolf
 */
public class Equation extends Expr{
    private String name = "NA";
    private Expr root = null;
    private Double value = null;
    private VariableMap variables = new VariableMap();
    private HashMap<String, Equation> subs = new HashMap<>();
    
    public Equation(){
        
    }
    public void setVariableMap(VariableMap variables){
        this.variables = variables;
        for(Equation e : subs.values()){
            e.setVariableMap(variables);
        }
    }
    @Override
    public double value() {
        if(value == null){
            value = root.value();
        }
        return value.doubleValue();
    }
    public double value(ArrayList<Variable> variableList){
        return value(variableList, true, null);
    }
    public double value(ArrayList<Variable> variableList, boolean reset, StringBuilder log){
        for(Variable v : variableList){
            changeVariable(v.getName(), v.value());
        }
        return value();
    }
    public boolean changeVariable(String name, double aValue){
        Double test = variables.change(name, aValue);
        if(test != null){
            // make it dirty
            value = null;
        }
        return test != null;
    }
    public boolean addVariable(String name, double aValue){
        Double test = variables.add(name, aValue);
        if(test != null){
            // make it dirty
            value = null;
        }
        return test != null;
    }
    public void setEpsilon(double eps){
        variables.setEpsilon(eps);
    }

    public void setRoot(Expr root) {
        this.root = root;
    }

    public Expr getExpr(String name) {
        Expr out = subs.get(name);
        if(out == null){
            out = variables.getVariable(name);
        }
        return out;
    }
}
